home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / devel / tcl / tclx7_31.z / tclx7_31 / tcldev / tclX7.3a-p1 / src / tclXfstat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-25  |  13.0 KB  |  407 lines

  1. /*
  2.  * tclXfstat.c
  3.  *
  4.  * Extended Tcl fstat command.
  5.  *-----------------------------------------------------------------------------
  6.  * Copyright 1991-1993 Karl Lehenbauer and Mark Diekhans.
  7.  *
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies.  Karl Lehenbauer and
  11.  * Mark Diekhans make no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without express or
  13.  * implied warranty.
  14.  *-----------------------------------------------------------------------------
  15.  * $Id: tclXfstat.c,v 3.1 1994/01/25 01:07:01 markd Exp $
  16.  *-----------------------------------------------------------------------------
  17.  */
  18. #include "tclExtdInt.h"
  19.  
  20. #ifndef NO_SYS_SOCKET_H
  21.  
  22. #include <sys/types.h>
  23. #include <sys/socket.h>
  24. #include <netdb.h>
  25. #include <netinet/in.h>
  26. #include <arpa/inet.h>
  27.  
  28. #endif
  29.  
  30. /*
  31.  * Prototypes of internal functions.
  32.  */
  33. static int
  34. GetRemoteHost _ANSI_ARGS_((Tcl_Interp *interp,
  35.                            FILE       *filePtr));
  36.  
  37. static char *
  38. GetFileType _ANSI_ARGS_((struct stat  *statBufPtr));
  39.  
  40. static void
  41. ReturnStatList _ANSI_ARGS_((Tcl_Interp   *interp,
  42.                             FILE         *filePtr,
  43.                             struct stat  *statBufPtr));
  44.  
  45. static int
  46. ReturnStatArray _ANSI_ARGS_((Tcl_Interp   *interp,
  47.                              FILE         *filePtr,
  48.                              struct stat  *statBufPtr,
  49.                              char         *arrayName));
  50.  
  51. static int
  52. ReturnStatItem _ANSI_ARGS_((Tcl_Interp   *interp,
  53.                             FILE         *filePtr,
  54.                             struct stat  *statBufPtr,
  55.                             char         *itemName));
  56.  
  57. #ifndef NO_SYS_SOCKET_H
  58.  
  59. /*
  60.  *-----------------------------------------------------------------------------
  61.  *
  62.  * GetRemoteHost --
  63.  *     Return the remote host IP address and name (if it can be obtained)
  64.  * as a list.
  65.  *
  66.  * Parameters:
  67.  *   o interp (O) - List is returned in the result.
  68.  *   o filePtr (I) - Pointer to file.  Should be a socket connection.
  69.  * Returns:
  70.  *   TCL_OK or TCL_ERROR.
  71.  *-----------------------------------------------------------------------------
  72.  */
  73. static int
  74. GetRemoteHost (interp, filePtr)
  75.     Tcl_Interp *interp;
  76.     FILE       *filePtr;
  77. {
  78.     int                 socketFD, nameLen;
  79.     struct sockaddr_in  remote;
  80.     struct hostent     *hostEntry;
  81.  
  82.     socketFD = fileno (filePtr);
  83.     nameLen = sizeof (remote);
  84.  
  85.     if (getpeername (socketFD, (struct sockaddr *) &remote, &nameLen) < 0)
  86.         goto unixError;
  87.     Tcl_AppendElement (interp, inet_ntoa (remote.sin_addr));
  88.  
  89.     hostEntry = gethostbyaddr ((char *) &(remote.sin_addr.s_addr),
  90.                                sizeof (remote.sin_addr.s_addr),
  91.                                AF_INET);
  92.     if (hostEntry != NULL)
  93.         Tcl_AppendElement (interp, hostEntry->h_name);
  94.        
  95.     return TCL_OK;
  96.  
  97.   unixError:
  98.     Tcl_ResetResult (interp);
  99.     interp->result = Tcl_PosixError (interp);
  100.     return TCL_ERROR;
  101. }
  102. #else
  103.  
  104. /*
  105.  *-----------------------------------------------------------------------------
  106.  *
  107.  * GetRemoteHost --
  108.  *     Version of this functions that always returns an error on systems that
  109.  * don't have sockets.
  110.  *-----------------------------------------------------------------------------
  111.  */
  112. static int
  113. GetRemoteHost (interp, filePtr)
  114.     Tcl_Interp *interp;
  115.     FILE       *filePtr;
  116. {
  117.     interp->result = "sockets are not available on this system";
  118.     return TCL_ERROR;
  119. }
  120. #endif /* NO_SYS_SOCKET_H */
  121.  
  122. /*
  123.  *-----------------------------------------------------------------------------
  124.  *
  125.  * GetFileType --
  126.  *
  127.  *   Looks at stat mode and returns a text string indicating what type of
  128.  * file it is.
  129.  *
  130.  * Parameters:
  131.  *   o statBufPtr (I) - Pointer to a buffer initialized by stat or fstat.
  132.  * Returns:
  133.  *   A pointer static text string representing the type of the file.
  134.  *-----------------------------------------------------------------------------
  135.  */
  136. static char *
  137. GetFileType (statBufPtr)
  138.     struct stat  *statBufPtr;
  139. {
  140.     char *typeStr;
  141.  
  142.     /*
  143.      * Get a string representing the type of the file.
  144.      */
  145.     if (S_ISREG (statBufPtr->st_mode)) {
  146.         typeStr = "file";
  147.     } else if (S_ISDIR (statBufPtr->st_mode)) {
  148.         typeStr = "directory";
  149.     } else if (S_ISCHR (statBufPtr->st_mode)) {
  150.         typeStr = "characterSpecial";
  151.     } else if (S_ISBLK (statBufPtr->st_mode)) {
  152.         typeStr = "blockSpecial";
  153.     } else if (S_ISFIFO (statBufPtr->st_mode)) {
  154.         typeStr = "fifo";
  155.     } else if (S_ISLNK (statBufPtr->st_mode)) {
  156.         typeStr = "link";
  157.     } else if (S_ISSOCK (statBufPtr->st_mode)) {
  158.         typeStr = "socket";
  159.     } else {
  160.         typeStr = "unknown";
  161.     }
  162.  
  163.     return typeStr;
  164. }
  165.  
  166. /*
  167.  *-----------------------------------------------------------------------------
  168.  *
  169.  * ReturnStatList --
  170.  *
  171.  *   Return file stat infomation as a keyed list.
  172.  *
  173.  * Parameters:
  174.  *   o interp (I) - The list is returned in result.
  175.  *   o filePtr (I) - Pointer to the Tcl open file structure.
  176.  *   o statBufPtr (I) - Pointer to a buffer initialized by stat or fstat.
  177.  *-----------------------------------------------------------------------------
  178.  */
  179. static void
  180. ReturnStatList (interp, filePtr, statBufPtr)
  181.     Tcl_Interp   *interp;
  182.     FILE         *filePtr;
  183.     struct stat  *statBufPtr;
  184. {
  185.     char statList [200];
  186.  
  187.     sprintf (statList, 
  188.              "{atime %ld} {ctime %ld} {dev %ld} {gid %ld} {ino %ld} {mode %ld} ",
  189.               (long) statBufPtr->st_atime, (long) statBufPtr->st_ctime,
  190.           (long) statBufPtr->st_dev,   (long) statBufPtr->st_gid,
  191.           (long) statBufPtr->st_ino,   (long) statBufPtr->st_mode);
  192.     Tcl_AppendResult (interp, statList, (char *) NULL);
  193.  
  194.     sprintf (statList, 
  195.              "{mtime %ld} {nlink %ld} {size %ld} {uid %ld} {tty %d} {type %s}",
  196.              (long) statBufPtr->st_mtime,  (long) statBufPtr->st_nlink,
  197.          (long) statBufPtr->st_size,   (long) statBufPtr->st_uid,
  198.          (int) isatty (fileno (filePtr)), GetFileType (statBufPtr));
  199.     Tcl_AppendResult (interp, statList, (char *) NULL);
  200.  
  201. }
  202.  
  203. /*
  204.  *-----------------------------------------------------------------------------
  205.  *
  206.  * ReturnStatArray --
  207.  *
  208.  *   Return file stat infomation in an array.
  209.  *
  210.  * Parameters:
  211.  *   o interp (I) - Current interpreter, error return in result.
  212.  *   o filePtr (I) - Pointer to the Tcl open file structure.
  213.  *   o statBufPtr (I) - Pointer to a buffer initialized by stat or fstat.
  214.  *   o arrayName (I) - The name of the array to return the info in.
  215.  * Returns:
  216.  *   TCL_OK or TCL_ERROR.
  217.  *-----------------------------------------------------------------------------
  218.  */
  219. static int
  220. ReturnStatArray (interp, filePtr, statBufPtr, arrayName)
  221.     Tcl_Interp   *interp;
  222.     FILE         *filePtr;
  223.     struct stat  *statBufPtr;
  224.     char         *arrayName;
  225. {
  226.     char numBuf [30];
  227.  
  228.     sprintf (numBuf, "%ld", (long) statBufPtr->st_dev);
  229.     if  (Tcl_SetVar2 (interp, arrayName, "dev", numBuf, 
  230.                       TCL_LEAVE_ERR_MSG) == NULL)
  231.         return TCL_ERROR;
  232.  
  233.     sprintf (numBuf, "%ld", (long) statBufPtr->st_ino);
  234.     if  (Tcl_SetVar2 (interp, arrayName, "ino", numBuf,
  235.                          TCL_LEAVE_ERR_MSG) == NULL)
  236.         return TCL_ERROR;
  237.  
  238.     sprintf (numBuf, "%ld", (long) statBufPtr->st_mode);
  239.     if  (Tcl_SetVar2 (interp, arrayName, "mode", numBuf, 
  240.                       TCL_LEAVE_ERR_MSG) == NULL)
  241.         return TCL_ERROR;
  242.  
  243.     sprintf (numBuf, "%ld", (long) statBufPtr->st_nlink);
  244.     if  (Tcl_SetVar2 (interp, arrayName, "nlink", numBuf,
  245.                       TCL_LEAVE_ERR_MSG) == NULL)
  246.         return TCL_ERROR;
  247.  
  248.     sprintf (numBuf, "%ld", (long) statBufPtr->st_uid);
  249.     if  (Tcl_SetVar2 (interp, arrayName, "uid", numBuf,
  250.                       TCL_LEAVE_ERR_MSG) == NULL)
  251.         return TCL_ERROR;
  252.  
  253.     sprintf (numBuf, "%ld", (long) statBufPtr->st_gid);
  254.     if  (Tcl_SetVar2 (interp, arrayName, "gid", numBuf,
  255.                       TCL_LEAVE_ERR_MSG) == NULL)
  256.         return TCL_ERROR;
  257.  
  258.     sprintf (numBuf, "%ld", (long) statBufPtr->st_size);
  259.     if  (Tcl_SetVar2 (interp, arrayName, "size", numBuf,
  260.                       TCL_LEAVE_ERR_MSG) == NULL)
  261.         return TCL_ERROR;
  262.  
  263.     sprintf (numBuf, "%ld", (long) statBufPtr->st_atime);
  264.     if  (Tcl_SetVar2 (interp, arrayName, "atime", numBuf,
  265.                       TCL_LEAVE_ERR_MSG) == NULL)
  266.         return TCL_ERROR;
  267.  
  268.     sprintf (numBuf, "%ld", (long) statBufPtr->st_mtime);
  269.     if  (Tcl_SetVar2 (interp, arrayName, "mtime", numBuf,
  270.                       TCL_LEAVE_ERR_MSG) == NULL)
  271.         return TCL_ERROR;
  272.  
  273.     sprintf (numBuf, "%ld", (long) statBufPtr->st_ctime);
  274.     if  (Tcl_SetVar2 (interp, arrayName, "ctime", numBuf,
  275.                       TCL_LEAVE_ERR_MSG) == NULL)
  276.         return TCL_ERROR;
  277.  
  278.     if (Tcl_SetVar2 (interp, arrayName, "tty", 
  279.                      isatty (fileno (filePtr)) ? "1" : "0",
  280.                      TCL_LEAVE_ERR_MSG) == NULL)
  281.         return TCL_ERROR;
  282.  
  283.     if (Tcl_SetVar2 (interp, arrayName, "type", GetFileType (statBufPtr),
  284.                      TCL_LEAVE_ERR_MSG) == NULL)
  285.         return TCL_ERROR;
  286.  
  287.     return TCL_OK;
  288.  
  289. }
  290.  
  291. /*
  292.  *-----------------------------------------------------------------------------
  293.  *
  294.  * ReturnStatItem --
  295.  *
  296.  *   Return a single file status item.
  297.  *
  298.  * Parameters:
  299.  *   o interp (I) - Item or error returned in result.
  300.  *   o filePtr (I) - Pointer to the Tcl open file structure.
  301.  *   o statBufPtr (I) - Pointer to a buffer initialized by stat or fstat.
  302.  *   o itemName (I) - The name of the desired item.
  303.  * Returns:
  304.  *   TCL_OK or TCL_ERROR.
  305.  *-----------------------------------------------------------------------------
  306.  */
  307. static int
  308. ReturnStatItem (interp, filePtr, statBufPtr, itemName)
  309.     Tcl_Interp   *interp;
  310.     FILE         *filePtr;
  311.     struct stat  *statBufPtr;
  312.     char         *itemName;
  313. {
  314.     if (STREQU (itemName, "dev"))
  315.         sprintf (interp->result, "%ld", (long) statBufPtr->st_dev);
  316.     else if (STREQU (itemName, "ino"))
  317.         sprintf (interp->result, "%ld", (long) statBufPtr->st_ino);
  318.     else if (STREQU (itemName, "mode"))
  319.         sprintf (interp->result, "%ld", (long) statBufPtr->st_mode);
  320.     else if (STREQU (itemName, "nlink"))
  321.         sprintf (interp->result, "%ld", (long) statBufPtr->st_nlink);
  322.     else if (STREQU (itemName, "uid"))
  323.         sprintf (interp->result, "%ld", (long) statBufPtr->st_uid);
  324.     else if (STREQU (itemName, "gid"))
  325.         sprintf (interp->result, "%ld", (long) statBufPtr->st_gid);
  326.     else if (STREQU (itemName, "size"))
  327.         sprintf (interp->result, "%ld", (long) statBufPtr->st_size);
  328.     else if (STREQU (itemName, "atime"))
  329.         sprintf (interp->result, "%ld", (long) statBufPtr->st_atime);
  330.     else if (STREQU (itemName, "mtime"))
  331.         sprintf (interp->result, "%ld", (long) statBufPtr->st_mtime);
  332.     else if (STREQU (itemName, "ctime"))
  333.         sprintf (interp->result, "%ld", (long) statBufPtr->st_ctime);
  334.     else if (STREQU (itemName, "type"))
  335.         interp->result = GetFileType (statBufPtr);
  336.     else if (STREQU (itemName, "tty"))
  337.         interp->result = isatty (fileno (filePtr)) ? "1" : "0";
  338.     else if (STREQU (itemName, "remotehost")) {
  339.         if (GetRemoteHost (interp, filePtr) != TCL_OK)
  340.             return TCL_ERROR;
  341.     } else {
  342.         Tcl_AppendResult (interp, "Got \"", itemName, "\", expected one of ",
  343.                           "\"atime\", \"ctime\", \"dev\", \"gid\", \"ino\", ",
  344.                           "\"mode\", \"mtime\", \"nlink\", \"size\", ",
  345.                           "\"tty\", \"type\", \"uid\", or \"remotehost\"",
  346.                           (char *) NULL);
  347.         return TCL_ERROR;
  348.     }
  349.  
  350.     return TCL_OK;
  351.  
  352. }
  353.  
  354. /*
  355.  *-----------------------------------------------------------------------------
  356.  *
  357.  * Tcl_FstatCmd --
  358.  *     Implements the fstat TCL command:
  359.  *         fstat fileId ?item?|?stat arrayvar?
  360.  *
  361.  *-----------------------------------------------------------------------------
  362.  */
  363. int
  364. Tcl_FstatCmd (clientData, interp, argc, argv)
  365.     ClientData  clientData;
  366.     Tcl_Interp *interp;
  367.     int         argc;
  368.     char      **argv;
  369. {
  370.     FILE         *filePtr;
  371.     struct stat  statBuf;
  372.  
  373.     if ((argc < 2) || (argc > 4)) {
  374.         Tcl_AppendResult (interp, tclXWrongArgs, argv [0], 
  375.                           " fileId ?item?|?stat arrayVar?", (char *) NULL);
  376.         return TCL_ERROR;
  377.     }
  378.  
  379.     if (Tcl_GetOpenFile (interp, argv[1],
  380.                          FALSE, FALSE,  /* No checking */
  381.                          &filePtr) != TCL_OK)
  382.     return TCL_ERROR;
  383.     
  384.     if (fstat (fileno (filePtr), &statBuf)) {
  385.         interp->result = Tcl_PosixError (interp);
  386.         return TCL_ERROR;
  387.     }
  388.  
  389.     /*
  390.      * Return data in the requested format.
  391.      */
  392.     if (argc == 4) {
  393.         if (!STREQU (argv [2], "stat")) {
  394.             Tcl_AppendResult (interp, "expected item name of \"stat\" when ",
  395.                               "using array name", (char *) NULL);
  396.             return TCL_ERROR;
  397.         }
  398.         return ReturnStatArray (interp, filePtr, &statBuf, argv [3]);
  399.     }
  400.     if (argc == 3)
  401.         return ReturnStatItem (interp, filePtr, &statBuf, argv [2]);
  402.  
  403.     ReturnStatList (interp, filePtr, &statBuf);
  404.     return TCL_OK;
  405.  
  406. }
  407.